package com.ciaojian.pay.wxpay;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.http.HttpUtil;
import com.ciaojian.pay.wxpay.enums.WxApiType;
import com.ciaojian.pay.wxpay.enums.WxDomain;
import com.ciaojian.pay.wxpay.model.bean.AccessToken;
import com.ciaojian.pay.wxpay.model.bean.WxBean;
import com.ciaojian.pay.wxpay.model.response.SubMessageSendResponse;
import com.ciaojian.pay.wxpay.model.submessage.BaseTemplate;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信小程序 api
 *
 * @author Atlakyn
 */
@Component
public class WxMiniAppApi {
    @Resource
    private WxBean wxBean;
    private static WxBean staticWxBean;

    @PostConstruct
    public void init() {
        staticWxBean = wxBean;
    }

    /**
     * 发送订阅消息
     *
     * @param baseTemplate 消息模板
     * @return 发送结果
     * @throws JsonProcessingException json 转换异常
     */
    public static SubMessageSendResponse subscribeMessageSend(BaseTemplate baseTemplate) throws JsonProcessingException {
        return HttpHandle.executionByPost(WxApiType.SUBSCRIBE_MESSAGE_SEND,
                baseTemplate.toJsonStr(),
                getAccessToken(),
                SubMessageSendResponse.class);
    }

    public static String getAccessToken() throws JsonProcessingException {
        AccessToken accessToken = new AccessToken();
        accessToken.setAppid(staticWxBean.getAppId());
        accessToken.setSecret(staticWxBean.getAppSecret());

        Map<String,Object> map = HttpHandle.executionByGet(WxApiType.ACCESS_TOKEN, BeanUtil.beanToMap(accessToken),Map.class);

        if (map != null) {
            return String.valueOf(map.get("access_token"));
        }
        return null;
    }
}

class HttpHandle {

    /**
     * 执行请求
     *
     * @param token 传入 token
     * @return 请求结果
     */
    static <T> T executionByPost(WxApiType type, Object params, String token, Class<T> clazz) throws JsonProcessingException {
        // 请求地址
        String apiUrl = WxPayApi.getReqUrl(type, WxDomain.CHINA3, false);
        apiUrl = apiUrl.concat("?access_token=" + token);
        // 请求结果
        T t = null;
        if (params instanceof Map) {
            t = HttpHandle.doPost(apiUrl, (HashMap<String, Object>) params, clazz);
        }
        if (params instanceof String) {
            t = HttpHandle.doPost(apiUrl, params.toString(), clazz);
        }
        return t;
    }

    static <T> T executionByGet(WxApiType type, Object params, Class<T> clazz) throws JsonProcessingException {
        // 请求地址
        String apiUrl = WxPayApi.getReqUrl(type, WxDomain.CHINA3, false);
        // 请求结果
        return HttpHandle.doGet(apiUrl, (Map<String, Object>) params, clazz);
    }



    /**
     * 获取接口请求的 URL
     *
     * @param wxApiType {@link WxApiType} 支付 API 接口枚举
     * @param wxDomain  {@link WxDomain} 支付 API 接口域名枚举
     * @param isSandBox 是否是沙箱环境
     * @return {@link String} 返回完整的接口请求URL
     */
    public static String getReqUrl(WxApiType wxApiType, WxDomain wxDomain, boolean isSandBox) {
        if (wxDomain == null) {
            wxDomain = WxDomain.CHINA;
        }
        return wxDomain.getType()
                .concat(isSandBox ? WxApiType.SAND_BOX_NEW.getType() : "")
                .concat(wxApiType.getType());
    }

    /**
     * 获取 access_token
     *
     * @return 微信返回的 access_token
     */
//    private static String getAccessToken() throws JsonProcessingException {
//        AccessToken accessToken = ApplicationContextHelper.getBean(AccessToken.class);
//        Map map = execution(MiniAppApiType.ACCESS_TOKEN, BeanUtil.beanToMap(accessToken), false, Map.class);
//
//        if (map != null) {
//            return String.valueOf(map.get("access_token"));
//        }
//        return null;
//    }

//    static Map<String, Object> bean2Map(BaseRequest baseRequest) {
//        return BeanUtil.beanToMap(baseRequest);
//    }
    private static <T> T doGet(String url, Map<String, Object> params, Class<T> clazz) throws JsonProcessingException {
        String result = HttpUtil.get(url, params);
        return new ObjectMapper().readValue(result, clazz);
    }

    private static <T> T doPost(String url, Map<String, Object> params, Class<T> clazz) throws JsonProcessingException {
        String result = HttpUtil.post(url, params);
        return new ObjectMapper().readValue(result, clazz);
    }

    private static <T> T doPost(String url, String params, Class<T> clazz) throws JsonProcessingException {
        String result = HttpUtil.post(url, params);
        return new ObjectMapper().readValue(result, clazz);
    }
}
